<template>
  <div class="network-topology-wrapper">
    <!-- 缩放控制按钮 -->
    <div class="zoom-controls">
      <button @click="zoomIn" class="zoom-btn">+</button>
      <button @click="zoomOut" class="zoom-btn">-</button>
      <button @click="resetZoom" class="zoom-btn">⟲</button>
    </div>
    
    <!-- 拓扑图容器 -->
    <div ref="chartRef" class="network-topology-container"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, reactive } from 'vue';
import * as d3 from 'd3';
import { nodes, links } from '../data/topologyData';

const chartRef = ref(null);
const zoomState = reactive({
  scale: 1,
  translate: [0, 0]
});
let svg, g;

onMounted(() => {
  const container = d3.select(chartRef.value);
  const width = 1920;
  const height = 1080;

  // 创建缩放行为
  const zoom = d3.zoom()
    .scaleExtent([0.3, 3]) // 缩放范围限制
    .on('zoom', (event) => {
      // 更新缩放状态
      zoomState.scale = event.transform.k;
      zoomState.translate = [event.transform.x, event.transform.y];
      // 应用变换到容器
      g.attr('transform', event.transform);
    });

  // 创建 SVG 容器
  svg = container.append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("viewBox", [0, 0, width, height])
    .call(zoom); // 应用缩放行为

  // 创建一个分组用于应用缩放变换
  g = svg.append("g");

  // 绘制连线
  const link = g.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links)
    .enter().append("line")
    .attr("stroke", "#66b3ff")
    .attr("stroke-width", 1);

  // 绘制节点（图标 + 标签）
  const node = g.append("g")
    .attr("class", "nodes")
    .selectAll("g")
    .data(nodes)
    .enter().append("g")
    .attr("transform", d => `translate(${d.x}, ${d.y})`);

  // 渲染图标
  node.append("image")
    .attr("href", d => d.icon)
    .attr("width", 40)
    .attr("height", 40)
    .attr("x", -20)
    .attr("y", -20);

  // 渲染标签
  node.append("text")
    .text(d => d.label)
    .attr("x", 0)
    .attr("y", 30)
    .attr("text-anchor", "middle")
    .attr("fill", "#333")
    .attr("font-size", "12px");

  // 更新连线端点
  function updateLinks() {
    link
      .attr("x1", d => {
        const sourceNode = nodes.find(n => n.id === d.source);
        return sourceNode ? sourceNode.x : 0;
      })
      .attr("y1", d => {
        const sourceNode = nodes.find(n => n.id === d.source);
        return sourceNode ? sourceNode.y : 0;
      })
      .attr("x2", d => {
        const targetNode = nodes.find(n => n.id === d.target);
        return targetNode ? targetNode.x : 0;
      })
      .attr("y2", d => {
        const targetNode = nodes.find(n => n.id === d.target);
        return targetNode ? targetNode.y : 0;
      });
  }

  updateLinks();
});

// 放大功能
const zoomIn = () => {
  if (svg) {
    svg.transition().call(
      d3.zoom().on('zoom', (event) => {
        g.attr('transform', event.transform);
      }).scaleBy, 1.3
    );
  }
};

// 缩小功能
const zoomOut = () => {
  if (svg) {
    svg.transition().call(
      d3.zoom().on('zoom', (event) => {
        g.attr('transform', event.transform);
      }).scaleBy, 0.7
    );
  }
};

// 重置缩放
const resetZoom = () => {
  if (svg) {
    svg.transition().call(
      d3.zoom().on('zoom', (event) => {
        g.attr('transform', event.transform);
      }).transform, d3.zoomIdentity
    );
  }
};
</script>

<style scoped>
.network-topology-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.network-topology-container {
  width: 100%;
  height: 600px;
  overflow: hidden;
  border: 1px solid #e0e0e0;
}

/* 缩放控制按钮样式 */
.zoom-controls {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.zoom-btn {
  width: 30px;
  height: 30px;
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  transition: all 0.2s ease;
}

.zoom-btn:hover {
  background-color: #f5f5f5;
  border-color: #999;
}

.zoom-btn:active {
  background-color: #e0e0e0;
}
</style>
